package com.example.btchat.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;

import android.annotation.TargetApi;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;

import com.example.btchat.BTChat;
import com.example.btchat.Message;

public class MainActivity extends Activity
{
	private static final int REQUEST_ENABLE_BT = 1;
	
	public List<Connection> connections = new ArrayList<Connection>();
	private AcceptThread acceptThread;
	private BluetoothAdapter adapter;
	private JSONArray messages;
	private ReaderThread readerThread;
	private BluetoothServerSocket server;
	private LinearLayout viewMessages;
	private EditText viewNewMessage;
	
	@Override
	@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		messages = new JSONArray();
		
		if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
			getActionBar().setHomeButtonEnabled(false);
		
		viewNewMessage = (EditText) findViewById(R.id.newmessage);
		viewMessages = (LinearLayout) findViewById(R.id.messages);
		
		viewNewMessage.setOnEditorActionListener(new OnEditorActionListener()
		{
			@Override
			public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
			{
				boolean handled = false;
				if(actionId == EditorInfo.IME_ACTION_SEND)
				{
					sendMessage();
					handled = true;
				}
				return handled;
			}
		});
		
		adapter = BluetoothAdapter.getDefaultAdapter();
		
		if(adapter == null)
		{
			Toast.makeText(this, getString(R.string.msg_no_bluetooth), Toast.LENGTH_LONG).show();
			finish();
			return;
		}
		
		if(adapter.isEnabled())
			startServer();
		else
		{
			Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(intent, REQUEST_ENABLE_BT);
		}
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.activity_main, menu);
		return true;
	}
	
	public void onMessageSent(Message msg)
	{
		for(Connection connection : this.connections)
		{
			try
			{
				connection.output.write(msg.toString().getBytes());
			}
			catch(IOException e)
			{
				Toast.makeText(
					this,
					getString(R.string.msg_lost_connection, connection.socket.getRemoteDevice().getName()),
					Toast.LENGTH_SHORT).show();
				connection.close();
				this.connections.remove(connection);
			}
		}
		
		messages.put(msg);
		
		addMessage(msg);
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		// Handle item selection
		switch(item.getItemId())
		{
			case R.id.menu_make_discoverable:
				make_discoverable();
				return true;
			default:
				return super.onOptionsItemSelected(item);
		}
	}
	
	public void onSocketConnected(BluetoothSocket socket)
	{
		try
		{
			this.connections.add(new Connection(socket));
		}
		catch(IOException e)
		{
			return;
		}
		
		this.readerThread.interrupt(); // wake ReaderThread if he is sleeping
	}
	
	private void addMessage(Message msg)
	{
		TextView tv = new TextView(this);
		tv.setText(Html.fromHtml("<strong>" + msg.getSource() + "</strong>: "));
		tv.append(msg.getMessage());
		
		viewMessages.addView(tv);
	}
	
	private void make_discoverable()
	{
		Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
		intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
		startActivity(intent);
	}
	
	private void startServer()
	{
		try
		{
			server = adapter.listenUsingRfcommWithServiceRecord(BTChat.MY_NAME, BTChat.MY_UUID);
		}
		catch(IOException e)
		{
			Toast.makeText(this, getString(R.string.msg_no_connection), Toast.LENGTH_LONG).show();
			finish();
			return;
		}
		
		acceptThread = new AcceptThread(server, this);
		acceptThread.start();
		
		readerThread = new ReaderThread(this);
		readerThread.start();
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		if(requestCode == REQUEST_ENABLE_BT)
		{
			if(resultCode == RESULT_OK)
			{
				startServer();
				return;
			}
			else
			{
				Toast.makeText(this, getString(R.string.msg_bluetooth_not_active), Toast.LENGTH_LONG)
					.show();
				finish();
				return;
			}
		}
	}
	
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState)
	{
		super.onRestoreInstanceState(savedInstanceState);
		
		if(savedInstanceState == null)
			return;
		
		String data = savedInstanceState.getString("messages");
		if(data == null)
			return;
		
		try
		{
			messages = new JSONArray(data);
		}
		catch(JSONException e)
		{
			return;
		}
		
		viewMessages.removeAllViews();
		for(int i = 0; i < messages.length(); i++)
		{
			try
			{
				String str = messages.getString(i);
				Message msg = Message.fromString(str);
				addMessage(msg);
			}
			catch(JSONException e)
			{}
		}
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState)
	{
		super.onSaveInstanceState(outState);
		
		outState.putString("messages", messages.toString());
	}
	
	protected void sendMessage()
	{
		String source = adapter.getName();
		String message = viewNewMessage.getText().toString();
		viewNewMessage.setText("");
		
		onMessageSent(new Message(source, message));
	}
}
